#pragma semicolon 1
#pragma newdecls required
#include <sourcemod>
#include <sdktools>

#define CVAR_FLAGS 			FCVAR_NOTIFY
#define PARTICLE_ACHIEVED	"achieved"
#define PARTICLE_FIREWORK	"mini_fireworks"
#define SOUND_ACHIEVEMENT	"ui/pickup_misc42.wav"

StringMap g_hWeaponAllowed;

ConVar g_hCvarAllow; 
ConVar g_hHealthLeeched[11];
ConVar g_hPainPillsDecayRate;

bool g_bCvarAllow;
bool g_bIsTankActive;
bool g_bWeaponHandling;

enum struct esRewards
{
	int iWitchRewards;
	int iTankRewards;
	int iRewardsBound;
	bool bTankAlive;
	float fRewardsBase;
	float fDistMultiplier;
	float fHeadShotMultiplier;
	float fLowHealth;
	float fLowHealthMultiplier;
	float fPerRewardsMax;
	int iAllowedWeapons;
}

esRewards g_esRewards;

int g_iParticles[MAXPLAYERS+1][2];

float g_fPainPillsDecayRate;
float g_fRewarded[MAXPLAYERS + 1];

enum L4D2WeaponType 
{
	L4D2WeaponType_Unknown = 0,
	L4D2WeaponType_Pistol,
	L4D2WeaponType_Magnum,
	L4D2WeaponType_Rifle,
	L4D2WeaponType_RifleAk47,
	L4D2WeaponType_RifleDesert,
	L4D2WeaponType_RifleM60,
	L4D2WeaponType_RifleSg552,
	L4D2WeaponType_HuntingRifle,
	L4D2WeaponType_SniperAwp,
	L4D2WeaponType_SniperMilitary,
	L4D2WeaponType_SniperScout,
	L4D2WeaponType_SMG,
	L4D2WeaponType_SMGSilenced,
	L4D2WeaponType_SMGMp5,
	L4D2WeaponType_Autoshotgun,
	L4D2WeaponType_AutoshotgunSpas,
	L4D2WeaponType_Pumpshotgun,
	L4D2WeaponType_PumpshotgunChrome,
	L4D2WeaponType_Molotov,
	L4D2WeaponType_Pipebomb,
	L4D2WeaponType_FirstAid,
	L4D2WeaponType_Pills,
	L4D2WeaponType_Gascan,
	L4D2WeaponType_Oxygentank,
	L4D2WeaponType_Propanetank,
	L4D2WeaponType_Vomitjar,
	L4D2WeaponType_Adrenaline,
	L4D2WeaponType_Chainsaw,
	L4D2WeaponType_Defibrilator,
	L4D2WeaponType_GrenadeLauncher,
	L4D2WeaponType_Melee,
	L4D2WeaponType_UpgradeFire,
	L4D2WeaponType_UpgradeExplosive,
	L4D2WeaponType_BoomerClaw,
	L4D2WeaponType_ChargerClaw,
	L4D2WeaponType_HunterClaw,
	L4D2WeaponType_JockeyClaw,
	L4D2WeaponType_SmokerClaw,
	L4D2WeaponType_SpitterClaw,
	L4D2WeaponType_TankClaw
}

static const char ItemsGive[][] =
{
	"give health",
	"give adrenaline",
	"give pain_pills",
	"give first_aid_kit",
	"give defibrillator",
	"give rifle_m60",
	"give grenade_launcher",
	"upgrade_add LASER_SIGHT"
};

// ====================================================================================================
//					PLUGIN INFO / START / END
// ====================================================================================================
public Plugin myinfo =
{
	name = "L4D2 Rewards",
	author = "",
	description = "",
	version = "",
	url = ""
}

public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max)
{
	EngineVersion test = GetEngineVersion();
	if(test != Engine_Left4Dead2)
	{
		strcopy(error, err_max, "Plugin only supports Left 4 Dead 2.");
		return APLRes_SilentFailure;
	}
	return APLRes_Success;
}

public void OnLibraryAdded(const char[] name)
{
	if(strcmp(name, "WeaponHandling") == 0)
		g_bWeaponHandling = true;
}

public void OnLibraryRemoved(const char[] name)
{
	if(strcmp(name, "WeaponHandling") == 0)
		g_bWeaponHandling = false;
}

public void OnPluginStart()
{
	g_hCvarAllow = CreateConVar("l4d2_rewards_allow", "1" , "是否启用该插件", CVAR_FLAGS);
	g_hHealthLeeched[0] = CreateConVar("l4d2_rewards_health0", "50" , "击杀witch回多少血", CVAR_FLAGS, true, 0.0);
	g_hHealthLeeched[1] = CreateConVar("l4d2_rewards_health1", "50" , "击杀Tank回多少血", CVAR_FLAGS, true, 0.0);
	g_hHealthLeeched[2] = CreateConVar("l4d2_rewards_health2", "1" , "坦克存活时是否关闭特感击杀回血", CVAR_FLAGS);
	g_hHealthLeeched[3] = CreateConVar("l4d2_rewards_health3", "80" , "实际血量超过多少后击杀特感不再回血", CVAR_FLAGS, true, 0.0);
	g_hHealthLeeched[4] = CreateConVar("l4d2_rewards_health4", "3.0" , "击杀特感的基础回血量", CVAR_FLAGS, true, 0.0);
	g_hHealthLeeched[5] = CreateConVar("l4d2_rewards_health5", "0.01" , "击杀特感的回血距离加成", CVAR_FLAGS, true, 0.0);
	g_hHealthLeeched[6] = CreateConVar("l4d2_rewards_health6", "1.5" , "爆头击杀加成倍率", CVAR_FLAGS, true, 1.0);
	g_hHealthLeeched[7] = CreateConVar("l4d2_rewards_health7", "15.0" , "实际血量低于多少时有额外的回血倍率", CVAR_FLAGS, true, 0.0);
	g_hHealthLeeched[8] = CreateConVar("l4d2_rewards_health8", "1.5" , "实际血量低于设定值后的额外回血倍率", CVAR_FLAGS, true, 1.0);
	g_hHealthLeeched[9] = CreateConVar("l4d2_rewards_health9", "20.0" , "一次最大回血值", CVAR_FLAGS, true, 1.0);
	g_hHealthLeeched[10] = CreateConVar("l4d2_rewards_health10", "1966079" , "允许哪些武器击杀回血", CVAR_FLAGS, true, 0.0);
	
	g_hPainPillsDecayRate = FindConVar("pain_pills_decay_rate");
	g_hPainPillsDecayRate.AddChangeHook(ConVarChanged);

	g_hCvarAllow.AddChangeHook(ConVarChanged_Allow);
	for(int i; i < 11; i++)
		g_hHealthLeeched[i].AddChangeHook(ConVarChanged);

	g_bIsTankActive = FindTank(-1);
	
	g_hWeaponAllowed = new StringMap();
	g_hWeaponAllowed.SetValue("pistol", 1);
	g_hWeaponAllowed.SetValue("pistol_magnum", 2);
	g_hWeaponAllowed.SetValue("chainsaw", 4);
	g_hWeaponAllowed.SetValue("smg", 8);
	g_hWeaponAllowed.SetValue("smg_mp5", 16);
	g_hWeaponAllowed.SetValue("smg_silenced", 32);
	g_hWeaponAllowed.SetValue("pumpshotgun", 64);
	g_hWeaponAllowed.SetValue("shotgun_chrome", 128);
	g_hWeaponAllowed.SetValue("rifle", 256);
	g_hWeaponAllowed.SetValue("rifle_desert", 512);
	g_hWeaponAllowed.SetValue("rifle_ak47", 1024);
	g_hWeaponAllowed.SetValue("rifle_sg552", 2048);
	g_hWeaponAllowed.SetValue("autoshotgun", 4096);
	g_hWeaponAllowed.SetValue("shotgun_spas", 8192);
	g_hWeaponAllowed.SetValue("hunting_rifle", 16384);
	g_hWeaponAllowed.SetValue("sniper_military", 32768);
	g_hWeaponAllowed.SetValue("sniper_scout", 65536);
	g_hWeaponAllowed.SetValue("sniper_awp", 131072);
	g_hWeaponAllowed.SetValue("rifle_m60", 262144);
	g_hWeaponAllowed.SetValue("grenade_launcher", 524288);
	g_hWeaponAllowed.SetValue("melee", 1048576);
}

public void ConVarChanged_Allow(Handle convar, const char[] oldValue, const char[] newValue)
{
	IsAllowed();
}

public void OnConfigsExecuted()
{
	IsAllowed();
}

void IsAllowed()
{
	bool bCvarAllow = g_hCvarAllow.BoolValue;
	GetCvars();

	if(g_bCvarAllow == false && bCvarAllow == true)
	{
		g_bIsTankActive = FindTank(-1);
		g_bCvarAllow = true;
		HookEvent("round_end", Event_RemoveAll,	EventHookMode_PostNoCopy);
		HookEvent("tank_spawn", Event_TankSpawn, EventHookMode_PostNoCopy);
		HookEvent("player_team", Event_PlayerTeam);
		HookEvent("witch_killed", Event_WitchKilled);
		HookEvent("player_death", Event_PlayerDeath);
	}
	else if(g_bCvarAllow == true && bCvarAllow == false)
	{
		ResetPlugin();
		g_bCvarAllow = false;
		UnhookEvent("round_end", Event_RemoveAll, EventHookMode_PostNoCopy);
		UnhookEvent("tank_spawn", Event_TankSpawn, EventHookMode_PostNoCopy);
		UnhookEvent("player_team", Event_PlayerTeam);
		UnhookEvent("witch_killed", Event_WitchKilled);
		UnhookEvent("player_death", Event_PlayerDeath);
	}
}

public void ConVarChanged(Handle convar, const char[] oldValue, const char[] newValue)
{
	GetCvars();
}

void GetCvars()
{
	g_esRewards.iWitchRewards = g_hHealthLeeched[0].IntValue;
	g_esRewards.iTankRewards = g_hHealthLeeched[1].IntValue;
	g_esRewards.bTankAlive = g_hHealthLeeched[2].BoolValue;
	g_esRewards.iRewardsBound = g_hHealthLeeched[3].IntValue;
	g_esRewards.fRewardsBase = g_hHealthLeeched[4].FloatValue;
	g_esRewards.fDistMultiplier = g_hHealthLeeched[5].FloatValue;
	g_esRewards.fHeadShotMultiplier = g_hHealthLeeched[6].FloatValue;
	g_esRewards.fLowHealth = g_hHealthLeeched[7].FloatValue;
	g_esRewards.fLowHealthMultiplier = g_hHealthLeeched[8].FloatValue;
	g_esRewards.fPerRewardsMax = g_hHealthLeeched[9].FloatValue;
	g_esRewards.iAllowedWeapons = g_hHealthLeeched[10].IntValue;
	g_fPainPillsDecayRate = g_hPainPillsDecayRate.FloatValue;
}

public void OnPluginEnd()
{
	ResetPlugin();
}

public void OnMapStart()
{
	PrecacheParticle(PARTICLE_ACHIEVED);
	PrecacheParticle(PARTICLE_FIREWORK);
	PrecacheSound(SOUND_ACHIEVEMENT);
}

public void OnMapEnd()
{
	ResetPlugin();
}

void ResetPlugin()
{
	g_bIsTankActive = false;
	for(int i = 1; i <= MaxClients; i++)
	{
		g_fRewarded[i] = 0.0;
		RemoveEffects(i);
	}
}

void RemoveEffects(int client)
{
	int entity;
	entity = g_iParticles[client][0];
	if(IsValidEntRef(entity))
		RemoveEntity(entity);
	g_iParticles[client][0] = 0;

	entity = g_iParticles[client][1];
	if(IsValidEntRef(entity))
		RemoveEntity(entity);
	g_iParticles[client][1] = 0;
}

stock bool IsIncapacitated(int client) 
{
	return GetEntProp(client, Prop_Send, "m_isIncapacitated") > 0;
}

// ====================================================================================================
//					EVENTS
// ====================================================================================================
public void Event_RemoveAll(Event event, const char[] name, bool dontBroadcast)
{
	OnMapEnd();
}

public Action Event_TankSpawn(Event event, const char[] name, bool dontBroadcast)
{
	g_bIsTankActive = true;
}

public Action Event_PlayerTeam(Event event, const char[] name, bool dontBroadcast)
{
	RemoveEffects(GetClientOfUserId(event.GetInt("userid")));
}

public Action Event_WitchKilled(Event event, const char[] name, bool dontBroadcast)
{
	int killer = GetClientOfUserId(event.GetInt("userid"));
	if(killer == 0 || GetClientTeam(killer) != 2 || IsFakeClient(killer) || !IsPlayerAlive(killer))
		return;

	if(event.GetBool("oneshot"))
	{
		CreateEffects(killer);
		if(GetEntProp(killer, Prop_Send, "m_currentReviveCount") < FindConVar("survivor_max_incapacitated_count").IntValue)
			GiveAward(killer);
		else
		{
			CheatCommand(killer, "give health");
			PrintHintText(killer, "黑白状态下一枪秒杀Witch,完全恢复健康状态");
		}
	}
	
	if(IsIncapacitated(killer))
		return;
		
	int iCurrent_Health = GetClientHealth(killer);
	int iNew_Health = iCurrent_Health + g_esRewards.iWitchRewards;
	int iMax_Health = GetEntProp(killer, Prop_Data, "m_iMaxHealth");
	if(iCurrent_Health <= iMax_Health && iNew_Health > iMax_Health)
		SetEntityHealth(killer, iMax_Health);
	else
		SetEntityHealth(killer, iNew_Health);
}

public Action Event_PlayerDeath(Event event, const char[] name, bool dontBroadcast)
{
	int victim = GetClientOfUserId(event.GetInt("userid"));
	RemoveEffects(victim);
	
	if(victim == 0 || !IsClientInGame(victim) || GetClientTeam(victim) != 3)
		return;
		
	int iClass = GetEntProp(victim, Prop_Send, "m_zombieClass");
	if(iClass == 8)
		g_bIsTankActive = FindTank(victim);

	int attacker = GetClientOfUserId(event.GetInt("attacker"));
	if(attacker == 0 || !IsClientInGame(attacker) || GetClientTeam(attacker) != 2 || !IsPlayerAlive(attacker))
		return;

	if(!IsFakeClient(attacker))
	{
		if(iClass == 8)
		{
			CreateEffects(attacker);
			if(IsIncapacitated(attacker) || GetEntProp(attacker, Prop_Send, "m_currentReviveCount") >= FindConVar("survivor_max_incapacitated_count").IntValue)
			{
				CheatCommand(attacker, "give health");
				PrintHintText(attacker, "黑白或倒地状态下杀死Tank,完全恢复健康状态");
			}
			else
			{
				GiveAward(attacker);
				SetEntityHealth(attacker, GetClientHealth(attacker) + g_esRewards.iTankRewards);
			}
		}
	}

	if(IsIncapacitated(attacker) || (g_esRewards.bTankAlive && g_bIsTankActive))
		return;

	static int iRealHealth;
	iRealHealth = GetClientRealHealth(attacker);
	if(GetClientRealHealth(attacker) > g_esRewards.iRewardsBound)
		return;

	static char sWeapon[32];
	event.GetString("weapon", sWeapon, sizeof(sWeapon));

	int offset;
	g_hWeaponAllowed.GetValue(sWeapon, offset);
	if(offset == 0 || offset & g_esRewards.iAllowedWeapons == 0)
		return;

	static float iLeeched_Health;
	iLeeched_Health = g_esRewards.fRewardsBase;

	if(event.GetBool("headshot"))
		iLeeched_Health *= g_esRewards.fHeadShotMultiplier;
		
	if(iRealHealth < g_esRewards.fLowHealth)
		iLeeched_Health *= g_esRewards.fLowHealthMultiplier;

	static float vOrigin[3], vTarget[3];
	GetClientAbsOrigin(attacker, vOrigin);
	GetClientAbsOrigin(victim, vTarget);

	iLeeched_Health += g_esRewards.fDistMultiplier * GetVectorDistance(vOrigin, vTarget, false);
	
	if(iLeeched_Health > g_esRewards.fPerRewardsMax)
		iLeeched_Health = g_esRewards.fPerRewardsMax;

	SetEntityHealth(attacker, RoundToCeil(GetClientHealth(attacker) + iLeeched_Health)); 
}

public void OnClientDisconnect(int client)
{
	if(client == 0 || !IsClientInGame(client) || GetClientTeam(client) != 3 || GetEntProp(client, Prop_Send, "m_zombieClass") != 8)
		return;
		
	CreateTimer(0.1, TankDisconnectCheck, _, TIMER_FLAG_NO_MAPCHANGE);
}

stock int GetClientRealHealth(int client)
{
	return RoundToFloor(GetClientHealth(client) + GetTempHealth(client));
}

float GetTempHealth(int client)
{
	float fHealth = GetEntPropFloat(client, Prop_Send, "m_healthBuffer");
	fHealth -= (GetGameTime() - GetEntPropFloat(client, Prop_Send, "m_healthBufferTime")) * g_fPainPillsDecayRate;
	return fHealth < 0.0 ? 0.0 : fHealth;
}

public Action TankDisconnectCheck(Handle timer) 
{
	g_bIsTankActive = FindTank(-1);
}

stock bool FindTank(int client)
{
	for(int t = 1; t <= MaxClients; t++)
	{
		if(t != client && IsClientInGame(t) && GetClientTeam(t) == 3 && GetEntProp(t, Prop_Send, "m_zombieClass") == 8 && IsPlayerAlive(t))
			return true;
	}
	return false;
}

void GiveAward(int client)
{
	if(GetClientTeam(client) == 2)
	{
		CheatCommand(client, ItemsGive[GetRandomInt(0, sizeof(ItemsGive) - 1)]);
		if(g_bWeaponHandling && GetRandomInt(1, 10) > 8)
			g_fRewarded[client] = GetGameTime() + 300.0;
	}
}

void CreateEffects(int client, bool sound=true, int effects=3, float thirdtime=4.0 , float removetime=3.5, float replaytime=3.5)
{
	if(client && IsClientInGame(client) && IsPlayerAlive(client) && GetClientTeam(client) != 1)
	{
		// Thirdperson view
		if(thirdtime > 0.0)
		{
			// Survivor Thirdperson plugin sets 99999.3.
			if(GetEntPropFloat(client, Prop_Send, "m_TimeForceExternalView") != 99999.3)
				SetEntPropFloat(client, Prop_Send, "m_TimeForceExternalView", GetGameTime() + thirdtime);
		}

		// Sound
		if(sound)
			EmitSoundToAll(SOUND_ACHIEVEMENT, client, SNDCHAN_AUTO, SNDLEVEL_NORMAL, SND_NOFLAGS, SNDVOL_NORMAL, SNDPITCH_NORMAL, -1, NULL_VECTOR, NULL_VECTOR, true, 0.0);

		// Effect
		int entity;
		if(effects == 3 || effects == 1)
		{
			entity = CreateEntityByName("info_particle_system");
			if(entity != INVALID_ENT_REFERENCE)
			{
				DispatchKeyValue(entity, "effect_name", PARTICLE_ACHIEVED);
				DispatchSpawn(entity);
				ActivateEntity(entity);
				AcceptEntityInput(entity, "start");

				// Attach to survivor
				SetVariantString("!activator");
				AcceptEntityInput(entity, "SetParent", client);
				TeleportEntity(entity, view_as<float>({ 0.0, 0.0, 50.0 }), NULL_VECTOR, NULL_VECTOR);

				// Loop
				char sTemp[64];
				SetVariantString("OnUser1 !self:Start::0.0:-1");
				AcceptEntityInput(entity, "AddOutput");
				FormatEx(sTemp, sizeof(sTemp), "OnUser2 !self:Stop::%f:-1", replaytime);
				SetVariantString(sTemp);
				AcceptEntityInput(entity, "AddOutput");
				FormatEx(sTemp, sizeof(sTemp), "OnUser2 !self:FireUser1::%f:-1", replaytime + 0.1);
				SetVariantString(sTemp);
				AcceptEntityInput(entity, "AddOutput");
				FormatEx(sTemp, sizeof(sTemp), "OnUser2 !self:FireUser2::%f:-1", replaytime + 0.1);
				SetVariantString(sTemp);
				AcceptEntityInput(entity, "AddOutput");

				AcceptEntityInput(entity, "FireUser1");
				AcceptEntityInput(entity, "FireUser2");

				// Remove
				FormatEx(sTemp, sizeof(sTemp), "OnUser3 !self:Kill::%f:-1", removetime);
				SetVariantString(sTemp);
				AcceptEntityInput(entity, "AddOutput");
				AcceptEntityInput(entity, "FireUser3");

				g_iParticles[client][0] = EntIndexToEntRef(entity);
			}
		}

		if(effects == 3 || effects == 2)
		{
			entity = CreateEntityByName("info_particle_system");
			{
				DispatchKeyValue(entity, "effect_name", PARTICLE_FIREWORK);
				DispatchSpawn(entity);
				ActivateEntity(entity);
				AcceptEntityInput(entity, "start");

				// Attach to survivor
				SetVariantString("!activator");
				AcceptEntityInput(entity, "SetParent", client);
				TeleportEntity(entity, view_as<float>({ 0.0, 0.0, 50.0 }), NULL_VECTOR, NULL_VECTOR);

				// Loop
				char sTemp[64];
				SetVariantString("OnUser1 !self:Start::0.0:-1");
				AcceptEntityInput(entity, "AddOutput");
				SetVariantString("OnUser2 !self:Stop::4.0:-1");
				AcceptEntityInput(entity, "AddOutput");
				SetVariantString("OnUser2 !self:FireUser1::4.0:-1");
				AcceptEntityInput(entity, "AddOutput");

				AcceptEntityInput(entity, "FireUser1");
				AcceptEntityInput(entity, "FireUser2");

				// Remove
				FormatEx(sTemp, sizeof(sTemp), "OnUser3 !self:Kill::%f:-1", removetime);
				SetVariantString(sTemp);
				AcceptEntityInput(entity, "AddOutput");
				AcceptEntityInput(entity, "FireUser3");

				g_iParticles[client][1] = EntIndexToEntRef(entity);
			}
		}
	}
}

void PrecacheParticle(const char[] sEffectName)
{
	static int table = INVALID_STRING_TABLE;

	if(table == INVALID_STRING_TABLE)
		table = FindStringTable("ParticleEffectNames");

	if(FindStringIndex(table, sEffectName) == INVALID_STRING_INDEX)
	{
		bool save = LockStringTables(false);
		AddToStringTable(table, sEffectName);
		LockStringTables(save);
	}
}

bool IsValidEntRef(int entity)
{
	if(entity && EntRefToEntIndex(entity) != INVALID_ENT_REFERENCE)
		return true;
	return false;
}

void CheatCommand(int client, const char[] sCommand)
{
	if(client == 0 || !IsClientInGame(client))
		return;

	char sCmd[32];
	if(SplitString(sCommand, " ", sCmd, sizeof(sCmd)) == -1)
		strcopy(sCmd, sizeof(sCmd), sCommand);

	int bits = GetUserFlagBits(client);
	SetUserFlagBits(client, ADMFLAG_ROOT);
	int flags = GetCommandFlags(sCmd);
	SetCommandFlags(sCmd, flags & ~FCVAR_CHEAT);
	FakeClientCommand(client, sCommand);
	SetCommandFlags(sCmd, flags);
	SetUserFlagBits(client, bits);
	if(strncmp(sCmd, "give", 4) == 0 && strcmp(sCommand[5], "health") == 0)
		SetEntPropFloat(client, Prop_Send, "m_healthBuffer", 0.0); //防止有虚血时give health会超过100血
}

// ====================================================================================================
//					WEAPON HANDLING
// ====================================================================================================
public void WH_OnMeleeSwing(int client, int weapon, float &speedmodifier)
{
	speedmodifier = SpeedModifier(client, speedmodifier); //send speedmodifier to be modified
}

public void WH_OnStartThrow(int client, int weapon, L4D2WeaponType weapontype, float &speedmodifier)
{
	speedmodifier = SpeedModifier(client, speedmodifier);
}

public void WH_OnReadyingThrow(int client, int weapon, L4D2WeaponType weapontype, float &speedmodifier)
{
	speedmodifier = SpeedModifier(client, speedmodifier);
}

public void WH_OnReloadModifier(int client, int weapon, L4D2WeaponType weapontype, float &speedmodifier)
{
	speedmodifier = SpeedModifier(client, speedmodifier);
}

public void WH_OnGetRateOfFire(int client, int weapon, L4D2WeaponType weapontype, float &speedmodifier)
{
	switch(weapontype)
	{
		case L4D2WeaponType_Rifle, L4D2WeaponType_RifleSg552, 
			L4D2WeaponType_SMG, L4D2WeaponType_RifleAk47, L4D2WeaponType_SMGMp5, 
			L4D2WeaponType_SMGSilenced, L4D2WeaponType_RifleM60:
		{
				return;
		}
	}

	speedmodifier = SpeedModifier(client, speedmodifier);
}

public void WH_OnDeployModifier(int client, int weapon, L4D2WeaponType weapontype, float &speedmodifier)
{
	speedmodifier = SpeedModifier(client, speedmodifier);
}

float SpeedModifier(int client, float speedmodifier)
{
	if(g_fRewarded[client] > GetGameTime())
		speedmodifier = speedmodifier * 2.0;// multiply current modifier to not overwrite any existing modifiers already

	return speedmodifier;
}